Trò chơi Tic-Tac-Toe, game đánh caro full source code
- PingCloudRegions.cs
- PhotonNetwork /
- Plugins /
- Photon Unity Networking /
- Assets /
- project /
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.Diagnostics;
5 using System.Net;
6 using ExitGames.Client.Photon;
7 using UnityEngine;
8 using Debug = UnityEngine.Debug;
9
10
11 #if UNITY_EDITOR || (!UNITY_ANDROID && !UNITY_IPHONE && !UNITY_PS3 && !UNITY_WINRT)
12
13 using System.Net.Sockets;
14
15 /// <summary>Uses C# Socket class from System.Net.Sockets (as Unity usually does).</summary>
16 /// <remarks>Incompatible with Windows 8 Store/Phone API.</remarks>
17 public class PingMonoEditor : PhotonPing
18 {
19 private Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
20
21 public override bool StartPing(string ip)
22 {
23 base.Init();
24
25 try
26 {
27 sock.ReceiveTimeout = 5000;
28 sock.Connect(ip, 5055);
29
30 PingBytes[PingBytes.Length - 1] = PingId;
31 sock.Send(PingBytes);
32 PingBytes[PingBytes.Length - 1] = (byte)(PingId - 1);
33 }
34 catch (Exception e)
35 {
36 sock = null;
37 Console.WriteLine(e);
38 }
39
40 return false;
41 }
42
43 public override bool Done()
44 {
45 if (this.GotResult || sock == null)
46 {
47 return true;
48 }
49
50 if (sock.Available <= 0)
51 {
52 return false;
53 }
54
55 int read = sock.Receive(PingBytes, SocketFlags.None);
56 //Debug.Log("Got: " + SupportClass.ByteArrayToString(PingBytes));
57 bool replyMatch = PingBytes[PingBytes.Length - 1] == PingId && read == PingLength;
58 if (!replyMatch) Debug.Log("ReplyMatch is false! ");
59
60
61 this.Successful = read == PingBytes.Length && PingBytes[PingBytes.Length - 1] == PingId;
62 this.GotResult = true;
63 return true;
64 }
65
66 public override void Dispose()
67 {
68 try
69 {
70 sock.Close();
71 }
72 catch
73 {
74 }
75 sock = null;
76 }
77
78 }
79 #endif
80
81
82
83 public class PhotonPingManager
84 {
85 public bool UseNative;
86 public static int Attempts = 5;
87 public static bool IgnoreInitialAttempt = true;
88 public static int MaxMilliseconsPerPing = 800; // enter a value you're sure some server can beat (have a lower rtt)
89
90
91 public Region BestRegion
92 {
93 get
94 {
95 Region result = null;
96 int bestRtt = Int32.MaxValue;
97 foreach (Region region in PhotonNetwork.networkingPeer.AvailableRegions)
98 {
99 Debug.Log("BestRegion checks region: " + region);
100 if (region.Ping != 0 && region.Ping < bestRtt)
101 {
102 bestRtt = region.Ping;
103 result = region;
104 }
105 }
106
107 return (Region)result;
108 }
109 }
110
111 public bool Done { get { return this.PingsRunning == 0; } }
112 private int PingsRunning;
113
114
115 /// <remarks>
116 /// Affected by frame-rate of app, as this Coroutine checks the socket for a result once per frame.
117 /// </remarks>
118 public IEnumerator PingSocket(Region region)
119 {
120 region.Ping = Attempts*MaxMilliseconsPerPing;
121
122 this.PingsRunning++; // TODO: Add try-catch to make sure the PingsRunning are reduced at the end and that the lib does not crash the app
123 PhotonPing ping;
124 //Debug.Log("PhotonHandler.PingImplementation " + PhotonHandler.PingImplementation);
125 if (PhotonHandler.PingImplementation == typeof(PingNativeDynamic))
126 {
127 Debug.Log("Using constructor for new PingNativeDynamic()"); // it seems on android, the Activator can't find the default Constructor
128 ping = new PingNativeDynamic();
129 }
130 else
131 {
132 ping = (PhotonPing)Activator.CreateInstance(PhotonHandler.PingImplementation);
133 }
134
135 //Debug.Log("Ping is: " + ping + " type " + ping.GetType());
136
137 float rttSum = 0.0f;
138 int replyCount = 0;
139
140
141 // PhotonPing.StartPing() requires a plain IP address without port (on all but Windows 8 platforms).
142 // So: remove port and do the DNS-resolving if needed
143 string cleanIpOfRegion = region.HostAndPort;
144 int indexOfColon = cleanIpOfRegion.LastIndexOf(':');
145 if (indexOfColon > 1)
146 {
147 cleanIpOfRegion = cleanIpOfRegion.Substring(0, indexOfColon);
148 }
149 cleanIpOfRegion = ResolveHost(cleanIpOfRegion);
150 //Debug.Log("Resolved and port-less IP is: " + cleanIpOfRegion);
151
152
153 for (int i = 0; i < Attempts; i++)
154 {
155 bool overtime = false;
156 Stopwatch sw = new Stopwatch();
157 sw.Start();
158
159 try
160 {
161 ping.StartPing(cleanIpOfRegion);
162 }
163 catch (Exception e)
164 {
165 Debug.Log("catched: " + e);
166 this.PingsRunning--;
167 break;
168 }
169
170
171 while (!ping.Done())
172 {
173 if (sw.ElapsedMilliseconds >= MaxMilliseconsPerPing)
174 {
175 overtime = true;
176 break;
177 }
178 yield return 0; // keep this loop tight, to avoid adding local lag to rtt.
179 }
180 int rtt = (int)sw.ElapsedMilliseconds;
181
182
183 if (IgnoreInitialAttempt && i == 0)
184 {
185 // do nothing.
186 }
187 else if (ping.Successful && !overtime)
188 {
189 rttSum += rtt;
190 replyCount++;
191 region.Ping = (int)((rttSum) / replyCount);
192 //Debug.Log("region " + region.Code + " RTT " + region.Ping + " success: " + ping.Successful + " over: " + overtime);
193 }
194
195 yield return new WaitForSeconds(0.1f);
196 }
197
198 this.PingsRunning--;
199
200 //Debug.Log("this.PingsRunning: " + this.PingsRunning + " this debug: " + ping.DebugString);
201 yield return null;
202 }
203
204 #if UNITY_WINRT && !UNITY_EDITOR
205
206 public static string ResolveHost(string hostName)
207 {
208 return hostName;
209 }
210
211 #else
212
213 /// <summary>
214 /// Attempts to resolve a hostname into an IP string or returns empty string if that fails.
215 /// </summary>
216 /// <param name="hostName">Hostname to resolve.</param>
217 /// <returns>IP string or empty string if resolution fails</returns>
218 public static string ResolveHost(string hostName)
219 {
220 try
221 {
222 IPAddress[] address = Dns.GetHostAddresses(hostName);
223
224 if (address.Length == 1)
225 {
226 return address[0].ToString();
227 }
228
229 // if we got more addresses, try to pick a IPv4 one
230 for (int index = 0; index < address.Length; index++)
231 {
232 IPAddress ipAddress = address[index];
233 if (ipAddress != null)
234 {
235 string ipString = ipAddress.ToString();
236 if (ipString.IndexOf('.') >= 0)
237 {
238 return ipString;
239 }
240 }
241 }
242 }
243 catch (System.Exception e)
244 {
245 Debug.Log("Exception caught! " + e.Source + " Message: " + e.Message);
246 }
247
248 return String.Empty;
249 }
250 #endif
251 }
Debug.Log("Got: " + SupportClass.ByteArrayToString(PingBytes));
public static int MaxMilliseconsPerPing = 800; enter a value you're sure some server can beat (have a lower rtt)
Affected by frame-rate of app, as this Coroutine checks the socket for a result once per frame.
this.PingsRunning++; TODO: Add try-catch to make sure the PingsRunning are reduced at the end and that the lib does not crash the app
Debug.Log("PhotonHandler.PingImplementation " + PhotonHandler.PingImplementation);
Debug.Log("Using constructor for new PingNativeDynamic()"); it seems on android, the Activator can't find the default Constructor
Debug.Log("Ping is: " + ping + " type " + ping.GetType());
PhotonPing.StartPing() requires a plain IP address without port (on all but Windows 8 platforms).
So: remove port and do the DNS-resolving if needed
Debug.Log("Resolved and port-less IP is: " + cleanIpOfRegion);
yield return 0; keep this loop tight, to avoid adding local lag to rtt.
do nothing.
Debug.Log("region " + region.Code + " RTT " + region.Ping + " success: " + ping.Successful + " over: " + overtime);
Debug.Log("this.PingsRunning: " + this.PingsRunning + " this debug: " + ping.DebugString);
Attempts to resolve a hostname into an IP string or returns empty string if that fails.
Hostname to resolve.
if we got more addresses, try to pick a IPv4 one